﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Bson;
using JXT.PrimaryKey.Batman.Domain.Quotation.Models;
using JXT.PrimaryKey.Batman.Domain.Quotation.Repositories;
using JXT.PrimaryKey.Batman.Domain.Repositories.Mongo;

namespace JXT.PrimaryKey.Batman.Domain.Repositories.Quotation
{
    public class MongoRealTimeQuoteRepository : MongoRepositoryBase<RealTimeQuote, Guid>, IRealTimeQuoteRepository
    {
        public MongoRealTimeQuoteRepository(RepositoryContext context)
            : base((MongoRepositoryContext)context)
        {
        }

        public override void Add(RealTimeQuote entity)
        {
            if (!IsCollectionExists)
                setIndex();
            var query = Query.And(Query.EQ("Code", entity.Code), Query.EQ("MarketType", entity.MarketType));
            if (MongoQuery.Count(query) > 0)
            {
                var update = BuildUpdateQuery<RealTimeQuote>(entity, "Code", "MarketType");
                MongoQuery.Update(query, update);
            }
            else
            {
                MongoQuery.Insert<RealTimeQuote>(entity);
            }
        }

        public void Add(IEnumerable<RealTimeQuote> list)
        {
            foreach (var item in list)
            {
                Add(item);
            }
        }

        public int Count(MarketType type, DateTime date)
        {
            IMongoQuery query = Query.And(Query.EQ("MarketType", type), Query.EQ("UpdateTime", date.Date));
            return (int)MongoQuery.Count(query);
        }

        public RealTimeQuote GetSingle(string code, MarketType type = MarketType.Unknown, DateTime? date = null)
        {
            IMongoQuery query = Query.EQ("Code", code);
            if (type != MarketType.Unknown)
                query = Query.And(query, Query.EQ("MarketType", type));
            if (date != null)
                query = Query.And(query, Query.EQ("UpdateTime", date.Value.Date));
            return MongoQuery.FindAs<RealTimeQuote>(query)
                .SetSortOrder(SortBy.Descending("UpdateTime"))
                .SetLimit(1)
                .FirstOrDefault();
        }

        public IEnumerable<RealTimeQuote> GetList(string code, MarketType type = MarketType.Unknown, DateTime? startTime = null, DateTime? endTime = null)
        {
            IMongoQuery query = Query.EQ("Code", code);
            if (type != MarketType.Unknown)
                query = Query.And(query, Query.EQ("MarketType", type));
            if (startTime == null)
                query = Query.And(query, Query.GTE("UpdateTime", new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0)));
            else
                query = Query.And(query, Query.GTE("UpdateTime", startTime.Value));
            if (endTime != null)
                query = Query.And(query, Query.LT("UpdateTime", endTime.Value));
            return MongoQuery.FindAs<RealTimeQuote>(query)
                .SetSortOrder(SortBy.Descending("UpdateTime"))
                .ToList();
        }

        private void setIndex()
        {
            IMongoIndexKeys keys = IndexKeys.Descending("UpdateTime");
            IMongoIndexOptions options = IndexOptions.SetUnique(false);
            MongoQuery.CreateIndex(keys, options);
        }
    }
}
